package com.youka.bussiness.common.utils;

import com.google.common.collect.Lists;
import com.youka.bussiness.common.base.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: 渠道自定义工具类
 * @author: liujinliang
 */
@Slf4j
public class BaseUtil {


    /**
     * 正则表达式
     */
    private static Pattern placPat = Pattern.compile("[{](.)*?[}]");

    /**
     * 将String转为Double
     *
     * @param object 转换的对象
     * @return
     */
    public static Double strToDouble(Object object) {
        if (object != null) {
            try {
                Double db = Double.parseDouble(object.toString());
                return db;
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Double发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Double发生异常", e);
            }
        }
        return null;
    }

    /**
     * 将String转Integeer
     *
     * @param object 转换的对象
     * @return
     */
    public static Integer strToInteger(Object object) {
        if (object != null) {
            try {
                Integer in = Integer.parseInt(object.toString());
                return in;
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Integer发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Integer发生异常", e);
            }
        }
        return null;
    }

    /**
     * 将String转为BigDecimal
     *
     * @param object 转换的对象
     * @return
     */
    public static BigDecimal strToBigDecimal(Object object) {
        if (object != null) {
            if (!StringUtils.isEmpty(object.toString())) {
                try {
                    BigDecimal de = new BigDecimal(object.toString()).setScale(2, BigDecimal.ROUND_DOWN);
                    return de;
                } catch (Exception e) {
                    log.error("字符串[{}]格式化为BigDecimal发生异常", e, object);
                    throw new RuntimeException("字符串[{}]格式化为BigDecimal发生异常", e);
                }
            } else {
                return new BigDecimal(0);
            }
        } else {
            return new BigDecimal(0);
        }
    }

    /**
     * 将String转Boolean
     *
     * @param object 转换的对象
     * @return
     */
    public static Boolean strToBoolean(Object object) {
        if (object != null) {
            return Boolean.parseBoolean(object.toString());
        }
        return null;
    }

    /**
     * 字符串格式化为Float
     *
     * @param object 转换的对象
     * @return
     */
    public static Float strToFloat(Object object) {
        if (object != null) {
            try {
                return Float.parseFloat(object.toString());
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Float发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Float发生异常", e);
            }
        }
        return null;
    }

    /**
     * 字符串格式化为Long
     *
     * @param object 转换的对象
     * @return
     */
    public static Long strToLong(Object object) {
        if (object != null) {
            try {
                return Long.parseLong(object.toString());
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Long发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Long发生异常", e);
            }
        }
        return null;
    }

    /**
     * 字符串转Short
     *
     * @param object 转换的对象
     * @return
     */
    public static Short strToShort(Object object) {
        if (object != null) {
            try {
                return Short.parseShort(object.toString());
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Short发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Short发生异常", e);
            }
        }
        return null;
    }

    /**
     * 字符串转Char
     *
     * @param object 转换的对象
     * @return
     */
    public static Character strToChar(Object object) {
        if (object != null) {
            try {
                return object.toString().charAt(0);
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Character发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Character发生异常", e);
            }
        }
        return null;
    }

    /**
     * 字符串转时间戳
     *
     * @param object 转换的对象
     * @return
     */
    public static Timestamp strToTimestamp(Object object) {
        if (object != null) {
            try {
                return Timestamp.valueOf(object.toString());
            } catch (Exception e) {
                log.error("字符串[{}]格式化为Timestamp发生异常", e, object);
                throw new RuntimeException("字符串[{}]格式化为Timestamp发生异常", e);
            }
        }
        return null;
    }

    /**
     * 将Str转为日期
     *
     * @param object 转换的对象
     * @return
     */
    public static Date strToDate(Object object) {
        if (object != null) {
            String dateStr = object.toString();

            //日期型
            if (isDate(dateStr)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    Date date = sdf.parse(dateStr);
                    return date;
                } catch (Exception e) {
                    log.error("将日期[{}]格式化为[yyyy-MM-dd]时发生异常", e);
                    //发生异常不抛出 直接返回NULL
                    return null;
                }

                //日期时间型
            } else if (isDateTime(dateStr)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                try {
                    Date date = sdf.parse(dateStr);
                    return date;
                } catch (Exception e) {
                    log.error("将日期时间[{}]格式化为[yyyy-MM-dd HH:mm:ss.SSS]时发生异常", e);
                    //发生异常不抛出 直接返回NULL
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * 判断是否为日期型
     *
     * @param str
     * @return
     */
    public static boolean isDate(String str) {
        boolean convertSuccess = true;
        //指定日期格式为yyyy-MM-dd
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        try {
            //设置lenient为false.
            //否则SimpleDateFormat会比较宽松地验证日期，比如2007-02-29会被接受，并转换成2007-03-01
            format.setLenient(false);
            format.parse(str);
        } catch (Exception e) {
            log.error("判断[{}]是否为[yyyy-MM-dd]时发生异常", e);
            //如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            convertSuccess = false;
        }
        return convertSuccess;
    }

    /**
     * 判断是否为日期时间型
     *
     * @param str
     * @return
     */
    public static boolean isDateTime(String str) {
        boolean convertSuccess = true;
        //指定日期格式为yyyy-MM-dd HH:mm:ss.SSS
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        try {
            //设置lenient为false.
            //否则SimpleDateFormat会比较宽松地验证日期，比如2007-02-29会被接受，并转换成2007-03-01
            format.setLenient(false);
            format.parse(str);
        } catch (Exception e) {
            log.error("判断[{}]是否为[yyyy-MM-dd HH:mm:ss.SSS]时发生异常", e);
            //如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            convertSuccess = false;
        }
        return convertSuccess;
    }

    /**
     * 格式化错误信息
     *
     * @param message 带有占位符的信息字符串
     * @param args    占位符参数，数量必须和占位符数量匹配
     * @return
     */
    public static String assemble(String message, Object... args) {
        Matcher matcher = placPat.matcher(message);
        StringBuilder stringBuffer = new StringBuilder();
        int start = 0;

        for (int count = 0; matcher.find(start); start = matcher.end()) {
            stringBuffer.append(message, start, matcher.start());
            stringBuffer.append(args[count++]);
        }

        stringBuffer.append(message, start, message.length());
        return stringBuffer.toString();
    }

    /**
     * 截取List
     *
     * @param list
     * @param start
     * @param end
     * @return
     */
    public static List<?> subList(List<?> list, Integer start, Integer end) {
        //检查开始位置
        start = start == null ? 0 : start < 0 ? 0 : start;

        //检查结束位置
        end = end == null ? list.size() : end > list.size() ? list.size() : end;
        if (end <= start) {
            throw new RuntimeException("参数设置错误!");
        }
        return list.subList(start, end);
    }

    /**
     * 获取UUID
     *
     * @return
     */
    public static String getUuid() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 获取UUID
     *
     * @return
     */
    public static String getCode() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        int randomCode = UUID.randomUUID().toString().hashCode();
        //有可能是负数
        if (randomCode < 0) {
            randomCode = -randomCode;
        }
        String item = dateFormat.format(new Date()).concat(String.format("%011d", randomCode));
        return item.substring(0, item.length() - 2);
    }

    /**
     * 获取UUID
     *
     * @return
     */
    public static String getNewCode() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddss");
        int randomCode = UUID.randomUUID().toString().hashCode();
        //有可能是负数
        if (randomCode < 0) {
            randomCode = -randomCode;
        }
        return dateFormat.format(new Date()).concat(String.format("%011d", randomCode));
    }

    /**
     * 数组拷贝
     *
     * @param source 源数组
     * @param target 要复制的源对象类
     * @return
     */
    public static <T, K> List<T> listToList(List<K> source, Class<T> target) {
        try {
            List<T> list = Lists.newArrayList();
            if (!CollectionUtils.isEmpty(source)) {
                for (Object item : source) {
                    Object object = target.newInstance();
                    BeanUtils.copyProperties(item, object);
                    list.add((T) object);
                }
            }
            return list;
        } catch (Exception e) {
            throw new BaseException("CPL-100001", "数组拷贝发生异常");
        }
    }

    /**
     * @param str 待转换字符串
     * @return 转换后字符串
     * @throws UnsupportedEncodingException
     * @Description 将字符串中的emoji表情转换成可以在utf-8字符集数据库中保存的格式（表情占4个字节，需要utf8mb4字符集）
     */
    public static String emojiToUtf(String str) {
        String patternString = "([\\x{10000}-\\x{10ffff}\ud800-\udfff])";
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            try {
                matcher.appendReplacement(sb, "[[" + URLEncoder.encode(matcher.group(1), "UTF-8") + "]]");
            } catch (UnsupportedEncodingException e) {
                return str;
            }
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * @param str 转换后的字符串
     * @return 转换前的字符串
     * @throws
     * @Description 还原utf8数据库中保存的含转换后emoji表情的字符串
     */
    public static String utfToEmoji(String str) {
        String patternString = "\\[\\[(.*?)\\]\\]";
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            try {
                matcher.appendReplacement(sb, URLDecoder.decode(matcher.group(1), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                return str;
            }
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 生成订单商品核销码
     *
     * @return
     */
    public static String genVerifyCode() {
        String year = new SimpleDateFormat("yy").format(new Date());
        String day = String.format("%tj", new Date());
        double random = Math.random() * 10000000;
        while (random < 1000000) {
            random = Math.random() * 10000000;
        }
        int intRandom = Double.valueOf(random).intValue();
        String verifyCode = year + day + intRandom;
        return verifyCode;
    }

    public static Object mapToObject(Map<String, Object> map, Class<?> beanClass) {
        try {
            if (map == null) {
                return null;
            }
            Object obj = beanClass.newInstance();
            org.apache.commons.beanutils.BeanUtils.populate(obj, map);
            return obj;
        } catch (Exception e) {
            throw new BaseException("对象转换异常");
        }
    }

    //2、object转换为map
    public static Map<?, ?> objectToMap(Object obj) {
        if (obj == null) {
            return null;
        }
        return new org.apache.commons.beanutils.BeanMap(obj);
    }
}